/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#pragma once

#include <lib3d/Math_lib3d.h>
#include "Texture.h"
#include "TextureCubic.h"
#include "VertexBuffer.h"
#include "IndexBuffer.h"
#include "PointBuffer.h"
#include "RenderTarget.h"
#include "RenderList.h"
#include <pictureformat/PictureFormat.h>
#include <vector>
#include <string>

namespace liba {
class WindowImpl;

namespace lib3d {
namespace hard {

typedef std::vector<std::string> Strings;

class Hardware : public RenderTarget
{
	typedef std::vector< Strings > StringTable;
	Strings attribute_names;
	StringTable attribute_table;
	int current_selection;
	Strings preferred_attribute_values;
protected:
	void set_attribute_names(const Strings & names, const Strings & values);
	void add_attribute_table_row(const Strings & values);
	virtual bool set_mode_internal(WindowImpl * window, const Strings & attribute_values)=0;
public:
	Hardware()
	:	RenderTarget( Atom("#DefaultRenderTarget#") ),
		current_selection( 0 )
	{}
	virtual ~Hardware()
	{}
	// for user hardware reporting
	virtual std::string get_hardware_name()=0;
	// for mode negotiation and setting
	virtual std::string get_name()=0;

	bool set_attribute_preference( const std::string & name, const std::string & value );
	bool set_attribute_filter( const std::string & name, const Strings & values );

	const Strings & GetAttribute_names();
	std::string GetAttribute(const std::string & name);
	bool set_attribute(const std::string & name, const std::string & value);
	Strings GetAttribute_choices(const std::string & name);
	int get_mode_count();

	bool set_mode(WindowImpl * window);
	virtual void stop_mode()=0;

	virtual bool is_operational()const=0;

	// can alter render_list in some ways - sort models, reorder lights, etc.
	virtual void render( RenderList * render_list, RenderTarget * render_target )=0;

	/** This method is not allowed to return 0 */
	virtual Texture * create_texture(int mipmap_levels, const pictureformat::Format & desired_format, int width, int height)=0;
	/** This method is not allowed to return 0 */
	virtual TextureCubic * create_texture_cubic(int mipmap_levels, const pictureformat::Format & desired_format, int width, int height)=0;

	/** This method is not allowed to return 0 */
	virtual VertexBuffer * create_vertex_buffer( bool dynamic = false )=0;
	/** This method is not allowed to return 0 */
	virtual IndexBuffer * create_index_buffer()=0;
	/** This method is not allowed to return 0 */
	virtual PointBuffer * create_point_buffer()=0;
	/** This method can return 0 if render targets are unsupported */
	virtual RenderTarget * create_render_target(const Atom & render_target_name, int width, int height)=0;
//	virtual RenderTargetCubic * create_render_target(const Atom & render_target_name, int width, int height)=0;
	virtual TextureBase * get_render_target(const Atom & render_target_name)=0;

	virtual bool start_frame()=0;
	virtual void flip()=0;
	
	virtual Texture * grab_screen()
	{
		return NULL;
	}
};

} // namespace hard
} // namespace lib3d
} // namespace liba
using namespace liba;
